package com.demo;

import java.util.*;
import java.util.stream.Collectors;

public class RecommenderSystem {
    private Map<String, Integer> userIndexMap = new HashMap<>();
    private Map<String, Integer> itemIndexMap = new HashMap<>();
    private double[][] interestMatrix;
    private double[][] userSimilarity;
    private List<String> users;
    private List<String> items;

    // 构建兴趣矩阵
    public void buildInterestMatrix(List<UserAction> actions) {
        // 获取所有用户和商品
        Set<String> userSet = new HashSet<>();
        Set<String> itemSet = new HashSet<>();
        
        for (UserAction action : actions) {
            userSet.add(action.getUserId());
            itemSet.add(action.getItemId());
        }
        
        users = new ArrayList<>(userSet);
        items = new ArrayList<>(itemSet);
        Collections.sort(users);
        Collections.sort(items);
        
        // 建立索引映射
        for (int i = 0; i < users.size(); i++) {
            userIndexMap.put(users.get(i), i);
        }
        for (int i = 0; i < items.size(); i++) {
            itemIndexMap.put(items.get(i), i);
        }
        
        // 初始化兴趣矩阵
        interestMatrix = new double[users.size()][items.size()];
        
        // 填充兴趣矩阵
        for (UserAction action : actions) {
            int userIdx = userIndexMap.get(action.getUserId());
            int itemIdx = itemIndexMap.get(action.getItemId());
            
            double weight = 0;
            switch (action.getActionType()) {
                case "view":
                    weight = BehaviorWeights.VIEW;
                    break;
                case "favorite":
                    weight = BehaviorWeights.FAVORITE;
                    break;
                case "cart":
                    weight = BehaviorWeights.CART;
                    break;
                case "order":
                    weight = BehaviorWeights.ORDER;
                    break;
            }
            
            interestMatrix[userIdx][itemIdx] += weight * action.getCount();
        }
    }
    
    // 计算用户相似度
    public void calculateUserSimilarity() {
        int userCount = users.size();
        userSimilarity = new double[userCount][userCount];
        
        for (int i = 0; i < userCount; i++) {
            for (int j = 0; j < userCount; j++) {
                userSimilarity[i][j] = cosineSimilarity(
                    interestMatrix[i], interestMatrix[j]);
            }
        }
    }
    
    // 余弦相似度计算
    private double cosineSimilarity(double[] vecA, double[] vecB) {
        double dotProduct = 0.0;
        double normA = 0.0;
        double normB = 0.0;
        
        for (int i = 0; i < vecA.length; i++) {
            dotProduct += vecA[i] * vecB[i];
            normA += Math.pow(vecA[i], 2);
            normB += Math.pow(vecB[i], 2);
        }
        
        if (normA == 0 || normB == 0) {
            return 0;
        }
        return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
    }
    
    // 生成推荐
    public List<Recommendation> recommendItems(String targetUser, int topN) {
        if (!userIndexMap.containsKey(targetUser)) {
            return Collections.emptyList();
        }
        
        int targetUserIdx = userIndexMap.get(targetUser);
        Map<String, Double> recommendations = new HashMap<>();
        
        // 获取相似用户排序
        List<Integer> similarUsers = getSimilarUsers(targetUserIdx);
        
        for (int simUserIdx : similarUsers) {
            if (simUserIdx == targetUserIdx) continue;
            
            for (int itemIdx = 0; itemIdx < items.size(); itemIdx++) {
                // 只推荐目标用户未交互过的商品
                if (interestMatrix[targetUserIdx][itemIdx] == 0 && 
                    interestMatrix[simUserIdx][itemIdx] > 0) {
                    
                    String itemId = items.get(itemIdx);
                    double score = userSimilarity[targetUserIdx][simUserIdx] * 
                                  interestMatrix[simUserIdx][itemIdx];
                    
                    recommendations.merge(itemId, score, Double::sum);
                }
            }
        }
        
        // 按推荐分数排序并返回topN
        return recommendations.entrySet().stream()
            .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
            .limit(topN)
            .map(e -> new Recommendation(e.getKey(), e.getValue()))
            .collect(Collectors.toList());
    }
    
    // 获取相似用户列表(按相似度降序)
    private List<Integer> getSimilarUsers(int targetUserIdx) {
        List<Integer> similarUsers = new ArrayList<>();
        for (int i = 0; i < users.size(); i++) {
            if (i != targetUserIdx) {
                similarUsers.add(i);
            }
        }
        
        similarUsers.sort((a, b) -> Double.compare(
            userSimilarity[targetUserIdx][b],
            userSimilarity[targetUserIdx][a]));
        
        return similarUsers;
    }
}